home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 60 / IOPROG_60.ISO / soft / c++ / gsl-1.1.1-setup.exe / {app} / src / ode-initval / rk4imp.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-18  |  4.9 KB  |  210 lines

  1. /* ode-initval/rk4imp.c
  2.  * 
  3.  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
  4.  * 
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or (at
  8.  * your option) any later version.
  9.  * 
  10.  * This program is distributed in the hope that it will be useful, but
  11.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * General Public License for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /* Runge-Kutta 4, Gaussian implicit */
  21.  
  22. /* Author:  G. Jungman */
  23.  
  24. #include <config.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <gsl/gsl_math.h>
  28. #include <gsl/gsl_errno.h>
  29. #include <gsl/gsl_odeiv.h>
  30.  
  31. #include "odeiv_util.h"
  32.  
  33. typedef struct
  34. {
  35.   double *k1nu;
  36.   double *k2nu;
  37.   double *ytmp1;
  38.   double *ytmp2;
  39. }
  40. rk4imp_state_t;
  41.  
  42. static void *
  43. rk4imp_alloc (size_t dim)
  44. {
  45.   rk4imp_state_t *state = (rk4imp_state_t *) malloc (sizeof (rk4imp_state_t));
  46.  
  47.   if (state == 0)
  48.     {
  49.       GSL_ERROR_NULL ("failed to allocate space for rk4imp_state",
  50.               GSL_ENOMEM);
  51.     }
  52.  
  53.   state->k1nu = (double *) malloc (dim * sizeof (double));
  54.  
  55.   if (state->k1nu == 0)
  56.     {
  57.       free (state);
  58.       GSL_ERROR_NULL ("failed to allocate space for k1nu", GSL_ENOMEM);
  59.     }
  60.  
  61.   state->k2nu = (double *) malloc (dim * sizeof (double));
  62.  
  63.   if (state->k2nu == 0)
  64.     {
  65.       free (state->k1nu);
  66.       free (state);
  67.       GSL_ERROR_NULL ("failed to allocate space for k2nu", GSL_ENOMEM);
  68.     }
  69.  
  70.   state->ytmp1 = (double *) malloc (dim * sizeof (double));
  71.  
  72.   if (state->ytmp1 == 0)
  73.     {
  74.       free (state->k2nu);
  75.       free (state->k1nu);
  76.       free (state);
  77.       GSL_ERROR_NULL ("failed to allocate space for ytmp1", GSL_ENOMEM);
  78.     }
  79.  
  80.   state->ytmp2 = (double *) malloc (dim * sizeof (double));
  81.  
  82.   if (state->ytmp2 == 0)
  83.     {
  84.       free (state->ytmp1);
  85.       free (state->k2nu);
  86.       free (state->k1nu);
  87.       free (state);
  88.       GSL_ERROR_NULL ("failed to allocate space for ytmp2", GSL_ENOMEM);
  89.     }
  90.  
  91.   return state;
  92. }
  93.  
  94.  
  95. static int
  96. rk4imp_apply (void *vstate,
  97.           size_t dim,
  98.           double t,
  99.           double h,
  100.           double y[],
  101.           double yerr[],
  102.           const double dydt_in[],
  103.           double dydt_out[], 
  104.               const gsl_odeiv_system * sys)
  105. {
  106.   rk4imp_state_t *state = (rk4imp_state_t *) vstate;
  107.  
  108.   const double ir3 = 1.0 / M_SQRT3;
  109.   const int iter_steps = 3;
  110.   int status = 0;
  111.   int nu;
  112.   size_t i;
  113.  
  114.   double *const k1nu = state->k1nu;
  115.   double *const k2nu = state->k2nu;
  116.   double *const ytmp1 = state->ytmp1;
  117.   double *const ytmp2 = state->ytmp2;
  118.  
  119.   /* initialization step */
  120.   if (dydt_in != 0)
  121.     {
  122.       DBL_MEMCPY (k1nu, dydt_in, dim);
  123.     }
  124.   else
  125.     {
  126.       int s = GSL_ODEIV_FN_EVAL (sys, t, y, k1nu);
  127.       GSL_STATUS_UPDATE (&status, s);
  128.     }
  129.  
  130.   DBL_MEMCPY (k2nu, k1nu, dim);
  131.  
  132.   /* iterative solution */
  133.   for (nu = 0; nu < iter_steps; nu++)
  134.     {
  135.       for (i = 0; i < dim; i++)
  136.     {
  137.       ytmp1[i] =
  138.         y[i] + h * (0.25 * k1nu[i] + 0.5 * (0.5 - ir3) * k2nu[i]);
  139.       ytmp2[i] =
  140.         y[i] + h * (0.25 * k2nu[i] + 0.5 * (0.5 + ir3) * k1nu[i]);
  141.     }
  142.       {
  143.     int s =
  144.       GSL_ODEIV_FN_EVAL (sys, t + 0.5 * h * (1.0 - ir3), ytmp1, k1nu);
  145.     GSL_STATUS_UPDATE (&status, s);
  146.       }
  147.       {
  148.     int s =
  149.       GSL_ODEIV_FN_EVAL (sys, t + 0.5 * h * (1.0 + ir3), ytmp2, k2nu);
  150.     GSL_STATUS_UPDATE (&status, s);
  151.       }
  152.     }
  153.  
  154.   /* assignment */
  155.   for (i = 0; i < dim; i++)
  156.     {
  157.       const double d_i = 0.5 * (k1nu[i] + k2nu[i]);
  158.       if (dydt_out != NULL)
  159.     dydt_out[i] = d_i;
  160.       y[i] += h * d_i;
  161.       yerr[i] = h * h * d_i;    /* FIXME: is this an overestimate ? */
  162.     }
  163.  
  164.   return status;
  165. }
  166.  
  167. static int
  168. rk4imp_reset (void *vstate, size_t dim)
  169. {
  170.   rk4imp_state_t *state = (rk4imp_state_t *) vstate;
  171.  
  172.   DBL_ZERO_MEMSET (state->k1nu, dim);
  173.   DBL_ZERO_MEMSET (state->k2nu, dim);
  174.   DBL_ZERO_MEMSET (state->ytmp1, dim);
  175.   DBL_ZERO_MEMSET (state->ytmp2, dim);
  176.  
  177.   return GSL_SUCCESS;
  178. }
  179.  
  180. static unsigned int
  181. rk4imp_order (void *vstate)
  182. {
  183.   rk4imp_state_t *state = (rk4imp_state_t *) vstate;
  184.   state = 0; /* prevent warnings about unused parameters */
  185.   return 4;
  186. }
  187.  
  188. static void
  189. rk4imp_free (void *vstate)
  190. {
  191.   rk4imp_state_t *state = (rk4imp_state_t *) vstate;
  192.   free (state->k1nu);
  193.   free (state->k2nu);
  194.   free (state->ytmp1);
  195.   free (state->ytmp2);
  196.   free (state);
  197. }
  198.  
  199. static const gsl_odeiv_step_type rk4imp_type = { "rk4imp",    /* name */
  200.   1,                /* can use dydt_in */
  201.   0,                /* gives exact dydt_out */
  202.   &rk4imp_alloc,
  203.   &rk4imp_apply,
  204.   &rk4imp_reset,
  205.   &rk4imp_order,
  206.   &rk4imp_free
  207. };
  208.  
  209. const gsl_odeiv_step_type *gsl_odeiv_step_rk4imp = &rk4imp_type;
  210.